1   /*
2    * Copyright (C) 2011 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.base;
18  
19  import static com.google.common.truth.Truth.assertThat;
20  
21  import com.google.common.annotations.GwtCompatible;
22  import com.google.common.annotations.GwtIncompatible;
23  import com.google.common.collect.FluentIterable;
24  import com.google.common.collect.ImmutableList;
25  import com.google.common.testing.NullPointerTester;
26  import com.google.common.testing.SerializableTester;
27  
28  import junit.framework.TestCase;
29  
30  import java.util.Collections;
31  import java.util.List;
32  import java.util.Set;
33  
34  /**
35   * Unit test for {@link Optional}.
36   *
37   * @author Kurt Alfred Kluever
38   */
39  @GwtCompatible(emulated = true)
40  public final class OptionalTest extends TestCase {
41    public void testAbsent() {
42      Optional<String> optionalName = Optional.absent();
43      assertFalse(optionalName.isPresent());
44    }
45  
46    public void testOf() {
47      assertEquals("training", Optional.of("training").get());
48    }
49  
50    public void testOf_null() {
51      try {
52        Optional.of(null);
53        fail();
54      } catch (NullPointerException expected) {
55      }
56    }
57  
58    public void testFromNullable() {
59      Optional<String> optionalName = Optional.fromNullable("bob");
60      assertEquals("bob", optionalName.get());
61    }
62  
63    public void testFromNullable_null() {
64      // not promised by spec, but easier to test
65      assertSame(Optional.absent(), Optional.fromNullable(null));
66    }
67  
68    public void testIsPresent_no() {
69      assertFalse(Optional.absent().isPresent());
70    }
71  
72    public void testIsPresent_yes() {
73      assertTrue(Optional.of("training").isPresent());
74    }
75  
76    public void testGet_absent() {
77      Optional<String> optional = Optional.absent();
78      try {
79        optional.get();
80        fail();
81      } catch (IllegalStateException expected) {
82      }
83    }
84  
85    public void testGet_present() {
86      assertEquals("training", Optional.of("training").get());
87    }
88  
89    public void testOr_T_present() {
90      assertEquals("a", Optional.of("a").or("default"));
91    }
92  
93    public void testOr_T_absent() {
94      assertEquals("default", Optional.absent().or("default"));
95    }
96  
97    public void testOr_supplier_present() {
98      assertEquals("a", Optional.of("a").or(Suppliers.ofInstance("fallback")));
99    }
100 
101   public void testOr_supplier_absent() {
102     assertEquals("fallback", Optional.absent().or(Suppliers.ofInstance("fallback")));
103   }
104 
105   public void testOr_nullSupplier_absent() {
106     Supplier<Object> nullSupplier = Suppliers.ofInstance(null);
107     Optional<Object> absentOptional = Optional.absent();
108     try {
109       absentOptional.or(nullSupplier);
110       fail();
111     } catch (NullPointerException expected) {
112     }
113   }
114 
115   public void testOr_nullSupplier_present() {
116     Supplier<String> nullSupplier = Suppliers.ofInstance(null);
117     assertEquals("a", Optional.of("a").or(nullSupplier));
118   }
119 
120   public void testOr_Optional_present() {
121     assertEquals(Optional.of("a"), Optional.of("a").or(Optional.of("fallback")));
122   }
123 
124   public void testOr_Optional_absent() {
125     assertEquals(Optional.of("fallback"), Optional.absent().or(Optional.of("fallback")));
126   }
127 
128   public void testOrNull_present() {
129     assertEquals("a", Optional.of("a").orNull());
130   }
131 
132   public void testOrNull_absent() {
133     assertNull(Optional.absent().orNull());
134   }
135 
136   public void testAsSet_present() {
137     Set<String> expected = Collections.singleton("a");
138     assertEquals(expected, Optional.of("a").asSet());
139   }
140 
141   public void testAsSet_absent() {
142     assertTrue("Returned set should be empty", Optional.absent().asSet().isEmpty());
143   }
144 
145   public void testAsSet_presentIsImmutable() {
146     Set<String> presentAsSet = Optional.of("a").asSet();
147     try {
148       presentAsSet.add("b");
149       fail();
150     } catch (UnsupportedOperationException expected) {
151     }
152   }
153 
154   public void testAsSet_absentIsImmutable() {
155     Set<Object> absentAsSet = Optional.absent().asSet();
156     try {
157       absentAsSet.add("foo");
158       fail();
159     } catch (UnsupportedOperationException expected) {
160     }
161   }
162 
163   public void testTransform_absent() {
164     assertEquals(Optional.absent(), Optional.absent().transform(Functions.identity()));
165     assertEquals(Optional.absent(), Optional.absent().transform(Functions.toStringFunction()));
166   }
167 
168   public void testTransform_presentIdentity() {
169     assertEquals(Optional.of("a"), Optional.of("a").transform(Functions.identity()));
170   }
171 
172   public void testTransform_presentToString() {
173     assertEquals(Optional.of("42"), Optional.of(42).transform(Functions.toStringFunction()));
174   }
175 
176   public void testTransform_present_functionReturnsNull() {
177     try {
178       Optional.of("a").transform(
179           new Function<String, String>() {
180             @Override public String apply(String input) {
181               return null;
182             }
183           });
184       fail("Should throw if Function returns null.");
185     } catch (NullPointerException expected) {
186     }
187   }
188 
189   public void testTransform_abssent_functionReturnsNull() {
190     assertEquals(Optional.absent(),
191         Optional.absent().transform(
192           new Function<Object, Object>() {
193             @Override public Object apply(Object input) {
194               return null;
195             }
196           }));
197   }
198 
199   // TODO(kevinb): use EqualsTester
200 
201   public void testEqualsAndHashCode_absent() {
202     assertEquals(Optional.<String>absent(), Optional.<Integer>absent());
203     assertEquals(Optional.absent().hashCode(), Optional.absent().hashCode());
204   }
205 
206   public void testEqualsAndHashCode_present() {
207     assertEquals(Optional.of("training"), Optional.of("training"));
208     assertFalse(Optional.of("a").equals(Optional.of("b")));
209     assertFalse(Optional.of("a").equals(Optional.absent()));
210     assertEquals(Optional.of("training").hashCode(), Optional.of("training").hashCode());
211   }
212 
213   public void testToString_absent() {
214     assertEquals("Optional.absent()", Optional.absent().toString());
215   }
216 
217   public void testToString_present() {
218     assertEquals("Optional.of(training)", Optional.of("training").toString());
219   }
220 
221   public void testPresentInstances_allPresent() {
222     List<Optional<String>> optionals =
223         ImmutableList.of(Optional.of("a"), Optional.of("b"), Optional.of("c"));
224     assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "b", "c");
225   }
226 
227   public void testPresentInstances_allAbsent() {
228     List<Optional<Object>> optionals =
229         ImmutableList.of(Optional.absent(), Optional.absent());
230     assertThat(Optional.presentInstances(optionals)).isEmpty();
231   }
232 
233   public void testPresentInstances_somePresent() {
234     List<Optional<String>> optionals =
235         ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
236     assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "c");
237   }
238 
239   public void testPresentInstances_callingIteratorTwice() {
240     List<Optional<String>> optionals =
241         ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
242     Iterable<String> onlyPresent = Optional.presentInstances(optionals);
243     assertThat(onlyPresent).iteratesAs("a", "c");
244     assertThat(onlyPresent).iteratesAs("a", "c");
245   }
246 
247   public void testPresentInstances_wildcards() {
248     List<Optional<? extends Number>> optionals =
249         ImmutableList.<Optional<? extends Number>>of(Optional.<Double>absent(), Optional.of(2));
250     Iterable<Number> onlyPresent = Optional.presentInstances(optionals);
251     assertThat(onlyPresent).iteratesAs(2);
252   }
253 
254   private static Optional<Integer> getSomeOptionalInt() {
255     return Optional.of(1);
256   }
257 
258   private static FluentIterable<? extends Number> getSomeNumbers() {
259     return FluentIterable.from(ImmutableList.<Number>of());
260   }
261 
262   /*
263    * The following tests demonstrate the shortcomings of or() and test that the casting workaround
264    * mentioned in the method Javadoc does in fact compile.
265    */
266 
267   @SuppressWarnings("unused") // compilation test
268   public void testSampleCodeError1() {
269     Optional<Integer> optionalInt = getSomeOptionalInt();
270     // Number value = optionalInt.or(0.5); // error
271   }
272 
273   @SuppressWarnings("unused") // compilation test
274   public void testSampleCodeError2() {
275     FluentIterable<? extends Number> numbers = getSomeNumbers();
276     Optional<? extends Number> first = numbers.first();
277     // Number value = first.or(0.5); // error
278   }
279 
280   @SuppressWarnings("unused") // compilation test
281   public void testSampleCodeFine1() {
282     Optional<Number> optionalInt = Optional.of((Number) 1);
283     Number value = optionalInt.or(0.5); // fine
284   }
285 
286   @SuppressWarnings("unused") // compilation test
287   public void testSampleCodeFine2() {
288     FluentIterable<? extends Number> numbers = getSomeNumbers();
289 
290     // Sadly, the following is what users will have to do in some circumstances.
291 
292     @SuppressWarnings("unchecked") // safe covariant cast
293     Optional<Number> first = (Optional) numbers.first();
294     Number value = first.or(0.5); // fine
295   }
296 
297   @GwtIncompatible("SerializableTester")
298   public void testSerialization() {
299     SerializableTester.reserializeAndAssert(Optional.absent());
300     SerializableTester.reserializeAndAssert(Optional.of("foo"));
301   }
302 
303   @GwtIncompatible("NullPointerTester")
304   public void testNullPointers() {
305     NullPointerTester npTester = new NullPointerTester();
306     npTester.testAllPublicConstructors(Optional.class);
307     npTester.testAllPublicStaticMethods(Optional.class);
308     npTester.testAllPublicInstanceMethods(Optional.absent());
309     npTester.testAllPublicInstanceMethods(Optional.of("training"));
310   }
311 }